#include "EmbStdLib_Mailbox.h"

#define ENABLE_MAIN (0) // Enable main function example

void spinlock_init(spinlock_t *lock)
{
  lock->lock = 0;
}

void disable_interrupts()
{
  // Implement disabling interrupts
}

void enable_interrupts()
{
  // Implement enabling interrupts
}

void spinlock_lock(spinlock_t *lock)
{
  disable_interrupts();
  while (lock->lock)
  {
    enable_interrupts();
    disable_interrupts();
  }
  lock->lock = 1;
  enable_interrupts();
}

void spinlock_unlock(spinlock_t *lock)
{
  disable_interrupts();
  lock->lock = 0;
  enable_interrupts();
}

// Mailbox management structure
typedef struct
{
  mailbox_message_t messages[LC_COMMUNICATION_MAILBOX_MAX];
  int head;
  int tail;
  int count;
  spinlock_t lock;
} mailbox_t;

// Create mailbox
bool osMailCreate(mailbox_t *mailbox)
{
  mailbox->head = 0;
  mailbox->tail = 0;
  mailbox->count = 0;
  spinlock_init(&mailbox->lock);
  return true;
}

// Allocate mail
mailbox_message_t *osMailAlloc(mailbox_t *mailbox)
{
  spinlock_lock(&mailbox->lock);

  if (mailbox->count == LC_COMMUNICATION_MAILBOX_MAX)
  {
    spinlock_unlock(&mailbox->lock);
    return NULL; // Mailbox is full
  }

  mailbox_message_t *msg = &mailbox->messages[mailbox->tail];
  memset(msg, 0, sizeof(mailbox_message_t)); // 清空消息内容

  spinlock_unlock(&mailbox->lock);

  return msg;
}

// Put mail
bool osMailPut(mailbox_t *mailbox, mailbox_message_t *msg)
{
  spinlock_lock(&mailbox->lock);

  if (mailbox->count == LC_COMMUNICATION_MAILBOX_MAX)
  {
    spinlock_unlock(&mailbox->lock);
    return false; // Mailbox is full
  }

  mailbox->messages[mailbox->tail] = *msg;
  mailbox->tail = (mailbox->tail + 1) % LC_COMMUNICATION_MAILBOX_MAX;
  mailbox->count++;

  spinlock_unlock(&mailbox->lock);

  return true;
}

// Get mail
bool osMailGet(mailbox_t *mailbox, mailbox_message_t *msg)
{
  spinlock_lock(&mailbox->lock);

  if (mailbox->count == 0)
  {
    spinlock_unlock(&mailbox->lock);
    return false; // Mailbox is empty
  }

  *msg = mailbox->messages[mailbox->head];
  mailbox->head = (mailbox->head + 1) % LC_COMMUNICATION_MAILBOX_MAX;
  mailbox->count--;

  spinlock_unlock(&mailbox->lock);

  return true;
}

// Free mail
bool osMailFree(mailbox_message_t *msg)
{
  if (msg == NULL)
  {
    return false; // msg is already NULL
  }

  if (msg->message_payload != NULL)
  {
    memset(msg->message_payload, 0x00, msg->message_payload_length);
  }

  memset(msg, 0, sizeof(mailbox_message_t)); // Clear message content

  return true;
}

#if ENABLE_MAIN
int main(void)
{
  mailbox_t lc_communication_mailbox;

  // Initialize mailbox
  if (osMailCreate(&lc_communication_mailbox))
  {
    printf("Mailbox created successfully.\n");
  }
  else
  {
    printf("Failed to create mailbox.\n");
    return -1;
  }

  // Prepare some data
  char ptr_data[] = "Pointer Data";
  char payload_data[] = "Hello, World!";

  // Allocate a mail
  mailbox_message_t *msg = osMailAlloc(&lc_communication_mailbox);
  if (msg != NULL)
  {
    msg->message_id = 1;
    msg->message_ptr = ptr_data;
    msg->message_param0 = 123;
    msg->message_param1 = 456;
    msg->message_param2 = 789;
    msg->message_command = 0x01;
    msg->message_payload = payload_data;
    msg->message_payload_length = sizeof(payload_data);

    // Put mail
    if (osMailPut(&lc_communication_mailbox, msg))
    {
      printf("Message put successfully.\n");
    }
    else
    {
      printf("Failed to put message.\n");
      osMailFree(msg);
      return -1;
    }

    // Get mail
    mailbox_message_t recv_msg;
    if (osMailGet(&lc_communication_mailbox, &recv_msg))
    {
      printf("Message received: id=%d, ptr=%s, param0=%d, payload=%s\n",
             recv_msg.message_id, (char *)recv_msg.message_ptr, recv_msg.message_param0, recv_msg.message_payload);
      osMailFree(&recv_msg);
    }
    else
    {
      printf("Failed to get message.\n");
    }
  }
  else
  {
    printf("Failed to allocate message.\n");
    return -1;
  }

  return 0;
}
#endif
